import re
from google.appengine.ext import db

# ------------------
# validate n numbers
# ------------------
    
def digit(string, count=1, lessThan=None) :
    '''
    Validate that s is 2 numbers
    '''
    try:
        if lessThan is None: #default
            lessThan = int(string) + 1
        
        regexStr = "^[0-9]{" + str(count) + "}$"
        return (not re.match(regexStr, string) is None) and (int(string) < lessThan)
    except ValueError:
            return False

    
def quickSearch(searchString, searchFor) :
    '''
    Validates string for quickSearch.
    Zero or more of any character is valid (kinda silly to even check)
    '''
    return re.match('.+', searchString) is not None and (searchFor == 'tas' or searchFor == 'sections')
    
def dropDown(s) :
    '''
    return false if s is default --make selection-- 
    return false if s is blank
    return true otherwise
    '''
    return not s == '--make selection--' and not s == '' and (type(s) == type(str()) or type(s) == type(unicode()))

def coursesToTAs(taDict) :
    'looks at taFields and fails if ta name assigned to more than one course, or to one course more than once'
    badTas = dict()
    taToCourses = dict()
    
    for taField in taDict:
        taName = taDict[taField]
        if taName == "--make selection--":
            continue
        courseUnique = int(taField.split('ta')[1].split('##')[0])
        if taName not in taToCourses:
            taToCourses[taName] = courseUnique
        else:
            if taName in badTas:
                uniqueSet = badTas[taName]
                uniqueSet |= set([courseUnique,])
                badTas[taName] = uniqueSet
            else:
                badTas[taName] = set([taToCourses[taName], courseUnique])
    return badTas

def dropDownMult(s) :
    ''' 
    return false if s is blank
    return true otherwise
    '''
    return not s == ''

# -------------
# email address
# -------------

def validateEmail(email):
    '''
    Pulled this from http://code.activestate.com/recipes/65215/
    '''
    if len(email) > 7:
        if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None:
            return 1
    return 0    
    
# -----------
# Collections
# -----------

def validateNoIntersection(c1,c2):
    return not c1 & c2   

# -------------
# class info
# -------------

def validateCourseNumber(s) :
    '''
    Validates string for courseNumber.
    '''
    return not re.match('^(c|C)(s|S)[0-5][0-9]{2}[a-zA-Z]?$', s) is None

def validateUniqueCourse(num, name) :
    '''
    Ensures uniqueness of new courses. 
    '''
    courses = dict()
    for c in db.GqlQuery("SELECT * FROM Course"): courses[c.identifier] = c.name.lower()
    if num in courses:
        if courses[num] == name.lower():
            return False
    for v in courses.values() :
        if v == name.lower():
            return False
    return True

def validateUniqueMajor(s) :
    '''
    Ensures uniqueness of new majors. 
    '''
    majors = []
    for c in db.GqlQuery("SELECT * FROM Major"): majors.append(c.name.lower())
    for major in majors:
        if major == s.lower() :
            return False
    return True

def validateUniqueSpecialization(s) :
    '''
    Ensures uniqueness of new specializations. 
    '''
    sp = []
    for c in db.GqlQuery("SELECT * FROM Specialization"): sp.append(c.name.lower())
    for a in sp:
        if a == s.lower() :
            return False
    return True

def validateUniqueLanguage(s) :
    '''
    Ensures uniqueness of new specializations. 
    '''
    pls = []
    for c in db.GqlQuery("SELECT * FROM Language"): pls.append(c.name.lower())
    for a in pls:
        if a == s.lower() :
            return False
    return True

def validateUniqueUnique(s, semester) :
    '''
    Ensures uniqueness of new sections. 
    '''

    u = []
    for c in db.GqlQuery("SELECT * FROM Section WHERE semester = :1", semester ): u.append(c.uniqueNumber)
    for a in u:
        if a == int(s) :
            return False
    return True



def validateUniqueNumber(s) :
    '''
    Validates string for uniqueNumber.
    '''
    return not re.match('^[0-9]{5}$', s) is None

def validateEid(s):
    '''
    Validates eid
    '''
    #at least two lower case letters followed by any number of digits
    return re.match('^[a-z]{2}[a-z]*[0-9]{3}[0-9]*$', s) is not None

def validateUniqueEid(s, semester):
    '''
    Ensures uniqueness of new eids.
    '''
    eids = []
    for ta in db.GqlQuery("SELECT * FROM Ta WHERE semester = :semester", semester = semester): eids.append( ta.eid )
    for instructor in db.GqlQuery("SELECT * FROM Instructor"): eids.append( instructor.eid )
    for eid in eids:
        if eid == s:
            return False
    return True

def validateUniqueInstructor( fName, lName):
    '''
    Ensures uniqueness of new instructor names.
    '''
    names = dict()
    for instructor in db.GqlQuery("SELECT * FROM Instructor"): names[instructor.firstName.lower()] = instructor.lastName.lower()
    if fName in names:
        if names[fName.lower()] == lName.lower():
            return False
    return True


def validateUniqueTa( fName, lName):
    '''
    Ensures uniqueness of new TA names.
    '''
    names = dict()
    for instructor in db.GqlQuery("SELECT * FROM Ta"): names[instructor.firstName.lower()] = instructor.lastName.lower()
    if fName in names:
        if names[fName.lower()] == lName.lower():
            return False
    return True


def validateNumStudents(s) :
    '''
    Validates string for numStudents.
    '''
    return not re.match('^[1-9][0-9]{0,2}$', s) is None

def validateNumTas(s) :
    '''
    Validates string for numTas.
    '''
    return not re.match('^[0-9]$', s) is None

def validateFreeText(s) :
    '''
    Validates free text boxes.
    '''
    return (s.find("delete") == -1 and re.match('''^$''', s) is None)

# -------------
# instructor name
# -------------

def validateFirstName(s) :
    '''
    Validates string for firstName. May have any casing, only letters.
    '''
    return re.match('''^([A-Za-z]([A-Za-z\-])+)$''', s) is not None

def validateLastName(s) :
    '''
    Validates string for lastName. May have any casing and a single apostrophe after first letter.
    '''
    return re.match('''^(([A-Za-z])(')*[A-Za-z\-]*)$''', s) is not None

